package com.manong.controller;

import com.manong.config.redis.RedisService;
import com.manong.entity.Permission;
import com.manong.entity.UserInfo;
import com.manong.utils.JwtUtils;
import com.manong.utils.MenuTree;
import com.manong.utils.Result;
import com.manong.vo.RouterVo;
import com.manong.vo.TokenVo;
import io.jsonwebtoken.Jwts;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import com.manong.entity.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 李茂鑫
 * @Date 2025/1/15 14:33
 * @Descripition  刷新token类
 */
@RestController
@RequestMapping("/api/sysUser")
public class SysUserController {
    @Resource
    private RedisService redisService;
    @Resource
    private JwtUtils jwtUtils;

    /**
     * 刷新token方法
     * @param request
     * @return
     */
    @PostMapping("/refreshToken")
    public Result refreshToken(HttpServletRequest request) {
        String token = request.getHeader("token");
        //从前端header中获取前端提交的token
        if (token == null) {
            token = request.getParameter("token");
            //若header中没有，则从参数中获取token
        }
        //从Spring Security上下文获取token信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        //通过 Spring Security 获取当前认证信息，返回 Authentication 对象。
        //getPrincipal()：返回当前认证的主体信息，通常是用户的详细信息（UserDetails）
        String retoken = "";
        if (jwtUtils.ValidateToken(token, userDetails)) {
            retoken = jwtUtils.refreshToken(token);
        }
        //调用 JwtUtils 的 ValidateToken 方法验证传入的 token 是否有效，并且是否与当前用户的身份匹配。会重新生成一个心得token
        long expireTime = Jwts.parser().setSigningKey(jwtUtils.getSecret())
                .parseClaimsJws(retoken.replace("jwt_", ""))
                .getBody().getExpiration().getTime();
        //Jwts.parser()：使用 JJWT 库解析 JWT。
        //setSigningKey(jwtUtils.getSecret())：设置签名密钥，用于验证 token 的合法性。
        //parseClaimsJws(retoken.replace("jwt_", ""))：解析 JWT，replace("jwt_", "") 是去掉 token 前缀的操作。JJWT 解析后会返回一个包含 JWT 数据的对象。
        //getBody().getExpiration().getTime()：从 JWT 的 body 部分获取过期时间，并转换成毫秒时间戳。
        String oldTokenkey = "token_" + token;
        redisService.del(oldTokenkey);
        //清除原来的token信息
        String newTokenkey = "token_" + token;
        redisService.set(newTokenkey, retoken, jwtUtils.getExpiration()/1000);
        //将新生成的 token 存储到 Redis 中，设置过期时间（由 jwtUtils.getExpiration() 获取）。
        TokenVo tokenVo = new TokenVo(expireTime, retoken);
        return Result.ok().message("token生成成功");
    }

    /**
     * 获取用户信息
     * @return
     */

    @GetMapping("/getUserInfo")
    public Result getInfo() {
        //从Spring Security上下文获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        //判断authentication是否为空
        if (authentication == null) {
            return Result.error().message("用户信息查询失败");
        }
        //获取用户信息   强转
        User user = (User) authentication.getPrincipal();
        //用户权限集合
        List<Permission> permissionList = user.getPermissionList();

        //获取角色权限编码信息
        Object[] roles = permissionList.stream()
                .filter(Objects::nonNull) //过滤
                .map(Permission::getCode).toArray(); //获取权限编码，转换为数组
        //创建用户信息对象
        UserInfo userInfo = new UserInfo(user.getId(), user.getNickName(), user.getAvatar(), null, roles);
        //返回数据
        return Result.ok(userInfo).message("用户信息查询成功");
    }
    /**
     * 获取菜单数据
     *
     * @return
     */
    @GetMapping("/getMenuList")
    public Result getMenuList() {
        //从Spring Security上下文获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取用户信息
        User user = (User) authentication.getPrincipal();
        //获取相应的权限
        List<Permission> permissionList = user.getPermissionList();
        //筛选目录和菜单
        List<Permission> collect = permissionList.stream()
                .filter(item -> item != null && item.getType() != 2)
                //不筛选按钮
                .collect(Collectors.toList());
        //0：菜单 1：目录 2：按钮
        //生成路由数据
        List<RouterVo> routerVoList = MenuTree.makeRouter(collect, 0L);
        //返回数据
        return Result.ok(routerVoList).message("菜单数据获取成功");
    }

    /**
     * 用户退出
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/logout")
    public Result logout(HttpServletRequest request, HttpServletResponse response) {
        //获取token
        String token = request.getHeader("token");
        //如果header中没有token，则从参数中获取token
        if (ObjectUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }
        //获取用户相关信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            //清空用户信息
            String key = "token_" + token;
            redisService.del(key);
        }
        return Result.ok().message("用户退出成功");
    }
}



